package yl.hs.bmipfull.service.host.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import yl.hs.bmipfull.daos.material.IRawMaterialInventoryDao;
import yl.hs.bmipfull.daos.production.IProductionRecordDao;
import yl.hs.bmipfull.daos.production.IProductionRecordDetailsDao;
import yl.hs.bmipfull.daos.production.IProductionTaskDao;
import yl.hs.bmipfull.daos.system.IAppSettingDao;
import yl.hs.bmipfull.daos.host.IProductionLineCodeConfigDao;
import yl.hs.bmipfull.daos.host.IProductionLineRawConfigDao;
import yl.hs.bmipfull.pojo.laboratory.ProductCateEntity;
import yl.hs.bmipfull.pojo.material.WarehouseEntity;
import yl.hs.bmipfull.pojo.production.ProductionLineEntity;
import yl.hs.bmipfull.pojo.production.ProductionRecordDetailsEntity;
import yl.hs.bmipfull.pojo.production.ProductionRecordEntity;
import yl.hs.bmipfull.pojo.production.ProductionTaskEntity;
import yl.hs.bmipfull.pojo.system.AppSettingEntity;
import yl.hs.bmipfull.pojo.host.ProductionLineCodeConfigEntity;
import yl.hs.bmipfull.pojo.host.ProductionLineRawConfigEntity;
import yl.hs.bmipfull.service.host.IHostRecordService;
import yl.hs.bmipfull.service.laboratory.IProductCateService;
import yl.hs.bmipfull.service.material.IRMWarehouseService;
import yl.hs.bmipfull.service.system.impl.SystemBaseService;
import yl.hs.bmipfull.utils.Tl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 张凯
 * @apiNote 生产消耗信息 service实现
 * @since 21-10-23 下午 1:51 创建
 */
@Service
public class HostRecordServiceImpl extends SystemBaseService implements IHostRecordService {

    final
    IProductionLineCodeConfigDao codeConfigDao;

    final
    IProductionLineRawConfigDao rawConfigDao;


    final
    IProductionTaskDao taskDao;

    final
    IProductionRecordDao productionRecordDao;

    final
    IAppSettingDao appSettingDao;

    final
    IProductionRecordDetailsDao productionRecordDetailsDao;

    @Autowired
    IRMWarehouseService warehouseService;
    @Autowired
    IRawMaterialInventoryDao rawMaterialInventoryDao;

    @Autowired
    IProductCateService productCateService;

    public HostRecordServiceImpl(IProductionLineCodeConfigDao codeConfigDao, IProductionLineRawConfigDao rawConfigDao, IProductionTaskDao taskDao, IProductionRecordDao productionRecordDao, IAppSettingDao appSettingDao, IProductionRecordDetailsDao productionRecordDetailsDao) {
        this.codeConfigDao = codeConfigDao;
        this.rawConfigDao = rawConfigDao;
        this.taskDao = taskDao;
        this.productionRecordDao = productionRecordDao;
        this.appSettingDao = appSettingDao;
        this.productionRecordDetailsDao = productionRecordDetailsDao;
    }

    @Override
    public void saveProductRecord(List<Map<String, String>> records, ProductionLineEntity productLine) {
        ProductionLineCodeConfigEntity codeConfig = codeConfigDao.findBySN(productLine.getSn());

        String taskSnCode = codeConfig.getTaskSN();
        if (records != null) {
            for (Map<String, String> record : records) {
                ProductionRecordEntity productionRecord = new ProductionRecordEntity();
                ProductionTaskEntity taskEntity = null;

                String taskSn = "";
                if (!Tl.isEmpty(taskSnCode)) {
                    taskSn = record.get(taskSnCode);
                    if (!Tl.isEmpty(taskSn)) {
                        taskEntity = taskDao.findBySN(taskSn);
                    }
                }
                // 方量
                var actualOutput = 0.00F;
                if (!Tl.isEmpty(codeConfig.getDiskVol() )){
                    String outputStr = record.get(codeConfig.getDiskVol());
                    if (!Tl.isEmpty(outputStr)) {
                        try {
                            actualOutput = Float.parseFloat(outputStr);
                        } catch (NumberFormatException e) {
                            e.printStackTrace();
                        }
                    }
                }
                productionRecord.setActualOutput(actualOutput);
                // 生产时间
                var startTime = new Date();
                if (!Tl.isEmpty(codeConfig.getProductTime())) {
                    String startTimeStr = record.get(codeConfig.getProductTime());

                   if (!Tl.isEmpty(startTimeStr)){
                       if (startTimeStr.contains(".")){
                           try {
                               startTime = Tl.convertFromOADate(Double.parseDouble(startTimeStr));
                           } catch (ParseException e) {
                               startTime = new Date();
                           }
                       } else {
                           startTime = Tl.strToDate(startTimeStr);
                       }
                   }
                }
                productionRecord.setStartTime(startTime);
                // 接料时间
                var receivingTime = new Date();
                if (!Tl.isEmpty(codeConfig.getReceivingTime())) {
                    String receivingTimeStr = record.get(codeConfig.getReceivingTime());

                    if (!Tl.isEmpty(receivingTimeStr)){
                        if (receivingTimeStr.contains(".")){
                            try {
                                receivingTime = Tl.convertFromOADate(Double.parseDouble(receivingTimeStr));
                            } catch (ParseException e) {
                                receivingTime = new Date();
                            }
                        } else {
                            receivingTime = Tl.strToDate(receivingTimeStr);
                        }
                    }
                }
                productionRecord.setReceivingTime(receivingTime);
                // 配比编号
                var matchingNumber = "";
                if (!Tl.isEmpty(codeConfig.getMatchingNumber() )) {
                    String matchingNumberStr = record.get(codeConfig.getMatchingNumber());
                    if (!Tl.isEmpty(matchingNumberStr)) {
                        matchingNumber = matchingNumberStr;
                    }
                }
                productionRecord.setMatchingNumber(matchingNumber);
                //生产线编号
                productionRecord.setProductLineSn(productLine.getSn());
                // 车辆编号
                var carCode = "";
                if (!Tl.isEmpty(codeConfig.getTruckPlate() )) {
                    String carCodeStr = record.get(codeConfig.getTruckPlate());
                    if (!Tl.isEmpty(carCodeStr)) {
                        carCode = carCodeStr;
                    }
                }
                productionRecord.setCarCode(carCode);
                //车分组
                var carGroup = "";
                if (!Tl.isEmpty(codeConfig.getCarGroup()) && !Tl.isEmpty(record.get(codeConfig.getCarGroup()))) {
                        carGroup = record.get(codeConfig.getCarGroup());
                }
                productionRecord.setCarGroup(carGroup);
                //司机
                var driver = "";
                if (!Tl.isEmpty(codeConfig.getDriver())) {
                    driver = record.get(codeConfig.getDriver());
                }
                productionRecord.setDriver(driver);
                //操作员
                var operator = "";
                if (!Tl.isEmpty(codeConfig.getOperator() )) {
                    operator = record.get(codeConfig.getOperator());
                }
                productionRecord.setOperator(operator);
                // 盘次
                var diskItem = "";
                var f=0.0;
                if (!Tl.isEmpty(codeConfig.getDiskNumber() )) {
                    diskItem = record.get(codeConfig.getDiskNumber());
                     f = Double.valueOf(diskItem);
                }
                productionRecord.setDiskItem((int)Math.ceil(f));

                if (taskEntity == null) {
                    //取传过来的生产任务数据

                    // 生成任务编号
                    productionRecord.setTaskSn("");
                    //工地名称
                    var projectName = "";
                    if (!Tl.isEmpty(codeConfig.getProjectName() )) {
                        projectName = record.get(codeConfig.getProjectName());
                    }
                    productionRecord.setProjectName(projectName);
                    //施工部位
                    var projectPart = "";
                    if (!Tl.isEmpty(codeConfig.getBuildPosition() )) {
                        projectPart = record.get(codeConfig.getBuildPosition());
                    }
                    if(Tl.isEmpty(projectPart) ) {
                        projectPart = "";
                    }
                    productionRecord.setProjectPart(projectPart);
                    //产品名称+产品规格
                    var productName = "";
                    if (!Tl.isEmpty(codeConfig.getProductName() )) {
                        productName = record.get(codeConfig.getProductName())+"-"+record.get(codeConfig.getProductSpecs());
                    }
                    productionRecord.setProductName(productName);
                    //产品种类
                    String[] split = productLine.getUseRang().split(",");
                    if ( split.length > 0){
                        ProductCateEntity productCate = productCateService.findBySn(split[0]);
                        productionRecord.setProductCate(productCate.getCateName());
                    }
                    if (Tl.isEmpty(taskSn)){
                        taskSn="";
                    }
                    productionRecord.setTaskSn(taskSn);

                } else {
                    //获取生产任务信息
                    productionRecord.setTaskSn(taskEntity.getSn());
                    productionRecord.setProjectName(taskEntity.getProjectName());
                    productionRecord.setProjectPart(taskEntity.getPosition());
                    productionRecord.setProductName(taskEntity.getProductName());
                    productionRecord.setProductCate(taskEntity.getProductCateName());
                }
                productionRecordDao.insertNew(productionRecord);
                updateLineMaxTime(productionRecord.getProductLineSn(),productionRecord.getStartTime());
                List<ProductionLineRawConfigEntity> rawConfigs = rawConfigDao.getListByPlSN(productLine.getSn());
                //保存明细信息
                for (ProductionLineRawConfigEntity rawConfig : rawConfigs) {
                    ProductionRecordDetailsEntity recordDetail = new ProductionRecordDetailsEntity();
                    recordDetail.setProductionRecordId(productionRecord.getId());
                    recordDetail.setRawMaterialSn(rawConfig.getRawSn());
                    recordDetail.setWarehouseSn(rawConfig.getWarehouseSn());
                    //配比值
                    var setValue =  BigDecimal.ZERO;
                    if (!Tl.isEmpty(rawConfig.getSetlValue())){
                        String setValueStr = record.get(rawConfig.getSetlValue());
                        if (!Tl.isEmpty(setValueStr)){
                            setValue = new BigDecimal(setValueStr);
                        }
                    }
                    recordDetail.setConfigRatioQuantity(setValue);
                    //实际值
                    var actualValue = BigDecimal.ZERO;
                    if (!Tl.isEmpty(rawConfig.getActualValue())){
                        String actualValueStr = record.get(rawConfig.getActualValue());
                        if (!Tl.isEmpty(actualValueStr)){
                            actualValue = new BigDecimal(actualValueStr);
                        }
                    }
                    recordDetail.setConsumptionQuantity(actualValue);
                    //差异值
                    recordDetail.setDifferenceQuantity(setValue.subtract(actualValue));

                    if(recordDetail.getConsumptionQuantity().compareTo(BigDecimal.ZERO)!=0 &&
                    recordDetail.getConfigRatioQuantity().compareTo(BigDecimal.ZERO)!=0 ) {
                        productionRecordDetailsDao.insertNew(recordDetail);
                        var wareHouse=rawMaterialInventoryDao.findByWHSNAndRmSN(rawConfig.getWarehouseSn(), rawConfig.getRawSn());
                        if(wareHouse!=null){
                            wareHouse.setQuantity(wareHouse.getQuantity().subtract(actualValue.divide(BigDecimal.valueOf(1000), RoundingMode.FLOOR)));
                            rawMaterialInventoryDao.update(wareHouse);
                            var cangKu=warehouseService.findBySn(wareHouse.getWhSN());
                            cangKu.setInventory(cangKu.getInventory().subtract(actualValue.divide(BigDecimal.valueOf(1000), RoundingMode.FLOOR)));
                            warehouseService.update(cangKu);
                        }
//                        WarehouseEntity warehouse = warehouseService.findBySn(rawConfig.getWarehouseSn());
//                        warehouse.setInventory(warehouse.getInventory().subtract(actualValue.divide(BigDecimal.valueOf(1000), RoundingMode.FLOOR)));
//                        warehouseService.update(warehouse);
                    }
                }

            }
        }
    }
    private static Map<String,Date> lineMaxTimeCache = new HashMap<>();
    private void updateLineMaxTime(String lineSN,Date time){
        if(lineMaxTimeCache.containsKey(lineSN)){
            var oldTime = lineMaxTimeCache.get(lineSN);
            if(time.getTime()>oldTime.getTime()){
                lineMaxTimeCache.replace(lineSN,time);
            }
        }
        else{
            lineMaxTimeCache.put(lineSN,time);
        }
    }

    @Override
    public Date getMaxTime(String sn,String type) {
        Date date=date = productionRecordDao.selectMaxTime(sn,type);;
//        if(lineMaxTimeCache.containsKey(sn)) {
//            date = lineMaxTimeCache.get(sn);
//        }
//        else{
//            date = productionRecordDao.selectMaxTime(sn,type);
//            if (date == null){
//                AppSettingEntity hostDefTimeAppSet = appSettingDao.getByCode("HostDefTime");
//                if ( hostDefTimeAppSet != null && !Tl.isEmpty(hostDefTimeAppSet.getParamValue())){
//                    date =  Tl.strToDate(hostDefTimeAppSet.getParamValue());
//                }
//            }
//            lineMaxTimeCache.put(sn,date);
//        }
        return date;
    }

    @Override
    public List<Map<String, Object>> queryCompareData(String lineSN, Date start, Date end) {
        var recordList = productionRecordDao.queryLineDataByTime(lineSN,start,end);
        var detailList = productionRecordDao.queryLineDetailDataByTime(lineSN,start,end);
        Calendar cal = Calendar.getInstance();
        cal.setTime(start);
        List<Map<String, Object>> data = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        while(start.compareTo(end)<=0){
            var dayString = sdf.format(start);
            Map<String, Object> dayItem = new HashMap<>();
            var dayStart = cal.getTime();
            cal.add(Calendar.DATE,1);
            var dayEnd = cal.getTime();
            var dayRecords = recordList.stream().filter(t->t.getStartTime().compareTo(dayStart)>=0 && t.getStartTime().compareTo(dayEnd)<=0).toList();
            var dayRecordIdList = dayRecords.stream().map(t->t.getId()).toList();
            var dayDetails = detailList.stream().filter(t->dayRecordIdList.contains(t.getProductionRecordId())).collect(Collectors.toList());
            dayItem.put("day",dayString);
            dayItem.put("actualOutput",dayRecords.stream().map(t->Tl.getBigDecimal(t.getActualOutput())).reduce(BigDecimal.ZERO,BigDecimal::add));
            dayItem.put("consumption",dayDetails.stream().map(t->t.getConsumptionQuantity()).reduce(BigDecimal.ZERO,BigDecimal::add));
            start = cal.getTime();
            data.add(dayItem);
        }
        return data;
    }

    @Override
    public Map<String, Object> querySummaryData(String lineSN, Date start, Date end) {
        var recordList = productionRecordDao.queryLineDataByTime(lineSN,start,end);
        var detailList = productionRecordDao.queryLineDetailDataByTime(lineSN,start,end);
        Map<String, Object> data = new HashMap<>();
        data.put("actualOutput",recordList.stream().map(t->Tl.getBigDecimal(t.getActualOutput())).reduce(BigDecimal.ZERO,BigDecimal::add));
        data.put("consumption",detailList.stream().map(t->t.getConsumptionQuantity()).reduce(BigDecimal.ZERO,BigDecimal::add));
        return data;
    }



}
